class Hook {
  constructor(args = []) {
    this.args = args // 存放参数数组
    this.taps = []  // 将来用于存放组装好的tap注册事件对象
    this._x = undefined  // 将来在HookCodeFactory中会给_x赋值为一个数组，里面包含从taps中遍历提取的每一个注册函数
  }

  // 注册同步钩子
  tap(options, fn) {
    // 将注册时传进来的名称转换为键值对形式
    if (typeof options === 'string') {
      options = { name: options }
    }
    options = Object.assign({ fn }, options)  // { fn:... name:fn1 }

    // 调用以下方法将组装好的options添加至taps数组
    this._insert(options)
  }

  // 注册异步钩子
  tapAsync(options, fn) {
    // 将注册时传进来的名称转换为键值对形式
    if (typeof options === 'string') {
      options = { name: options }
    }
    options = Object.assign({ fn }, options)  // { fn:... name:fn1 }

    // 调用以下方法将组装好的options添加至taps数组
    this._insert(options)
  }

  _insert(options) {
    this.taps[this.taps.length] = options
  }

  // 同步方法执行
  call(...args) {
    // 创建将来要具体执行的函数代码结构
    let callFn = this._createCall('sync')
    // 调用上述的函数（args传入进去）
    return callFn.apply(this, args)
  }

  // 异步方法执行
  callAsync(...args) {
    let callFn = this._createCall('async')
    return callFn.apply(this, args)
  }

  _createCall(type) {
    // 调用具体钩子类的compile方法，进行具体执行的函数代码组装
    return this.compile({
      taps: this.taps,
      args: this.args,
      type: type
    })
  }
}

module.exports = Hook
